package cn.sunyblog.tool.threadpool.strategy;

import cn.sunyblog.tool.threadpool.monitor.ThreadPoolMetrics;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.*;

/**
 * 动态线程池智能扩容算法测试
 * 验证用户需求：根据初始配置比例动态调整扩容策略
 */
public class DynamicThreadPoolTest {
    
    private DefaultAdjustmentStrategy strategy;
    
    @BeforeEach
    void setUp() {
        strategy = new DefaultAdjustmentStrategy();
    }
    
    /**
     * 测试队列主导型配置（如：队列2000，核心线程2）
     * 期望：优先扩容线程，队列保守扩容
     */
    @Test
    void testQueueDominantConfiguration() {
        // 模拟队列主导型配置：队列2000，核心线程2，最大线程4
        ThreadPoolMetrics metrics = createMockMetrics(
            2,    // 核心线程数
            4,    // 最大线程数
            2000, // 队列容量
            1800, // 队列使用数量（90%使用率）
            4,    // 当前线程数
            4,    // 活跃线程数
            100,  // 提交速率
            50,   // 完成速率
            10    // 拒绝任务数
        );
        
        AdjustmentStrategy.AdjustmentRecommendation recommendation = strategy.recommend(metrics);
        
        assertNotNull(recommendation, "队列主导型配置应该触发扩容");
        
        // 验证线程大幅扩容（队列主导型应该优先扩线程）
        assertTrue(recommendation.getNewCorePoolSize() >= 8, 
            String.format("核心线程应该大幅扩容，期望>=8，实际=%d", recommendation.getNewCorePoolSize()));
        assertTrue(recommendation.getNewMaximumPoolSize() >= 16, 
            String.format("最大线程应该大幅扩容，期望>=16，实际=%d", recommendation.getNewMaximumPoolSize()));
        
        // 验证队列保守扩容
        assertTrue(recommendation.getNewQueueCapacity() <= 2600, 
            String.format("队列应该保守扩容，期望<=2600，实际=%d", recommendation.getNewQueueCapacity()));
        
        System.out.println("队列主导型测试结果：");
        System.out.println(String.format("核心线程：2 -> %d", recommendation.getNewCorePoolSize()));
        System.out.println(String.format("最大线程：4 -> %d", recommendation.getNewMaximumPoolSize()));
        System.out.println(String.format("队列容量：2000 -> %d", recommendation.getNewQueueCapacity()));
        System.out.println("调整原因：" + recommendation.getReason());
    }
    
    /**
     * 测试线程主导型配置（如：队列20，核心线程50）
     * 期望：优先扩容队列，线程保守扩容
     */
    @Test
    void testThreadDominantConfiguration() {
        // 模拟线程主导型配置：队列20，核心线程50，最大线程100
        ThreadPoolMetrics metrics = createMockMetrics(
            50,   // 核心线程数
            100,  // 最大线程数
            20,   // 队列容量
            18,   // 队列使用数量（90%使用率）
            80,   // 当前线程数
            75,   // 活跃线程数
            200,  // 提交速率
            100,  // 完成速率
            5     // 拒绝任务数
        );
        
        AdjustmentStrategy.AdjustmentRecommendation recommendation = strategy.recommend(metrics);
        
        assertNotNull(recommendation, "线程主导型配置应该触发扩容");
        
        // 验证队列大幅扩容（线程主导型应该优先扩队列）
        assertTrue(recommendation.getNewQueueCapacity() >= 120, 
            String.format("队列应该大幅扩容，期望>=120，实际=%d", recommendation.getNewQueueCapacity()));
        
        // 验证线程保守扩容
        assertTrue(recommendation.getNewCorePoolSize() <= 70, 
            String.format("核心线程应该保守扩容，期望<=70，实际=%d", recommendation.getNewCorePoolSize()));
        assertTrue(recommendation.getNewMaximumPoolSize() <= 130, 
            String.format("最大线程应该保守扩容，期望<=130，实际=%d", recommendation.getNewMaximumPoolSize()));
        
        System.out.println("\n线程主导型测试结果：");
        System.out.println(String.format("核心线程：50 -> %d", recommendation.getNewCorePoolSize()));
        System.out.println(String.format("最大线程：100 -> %d", recommendation.getNewMaximumPoolSize()));
        System.out.println(String.format("队列容量：20 -> %d", recommendation.getNewQueueCapacity()));
        System.out.println("调整原因：" + recommendation.getReason());
    }
    
    /**
     * 测试平衡型配置（如：队列500，核心线程16，最大线程32）
     * 期望：标准扩容策略
     */
    @Test
    void testBalancedConfiguration() {
        // 模拟平衡型配置：队列500，核心线程16，最大线程32
        ThreadPoolMetrics metrics = createMockMetrics(
            16,   // 核心线程数
            32,   // 最大线程数
            500,  // 队列容量
            400,  // 队列使用数量（80%使用率）
            30,   // 当前线程数
            28,   // 活跃线程数
            150,  // 提交速率
            80,   // 完成速率
            3     // 拒绝任务数
        );
        
        AdjustmentStrategy.AdjustmentRecommendation recommendation = strategy.recommend(metrics);
        
        assertNotNull(recommendation, "平衡型配置应该触发扩容");
        
        // 验证标准扩容
        assertTrue(recommendation.getNewCorePoolSize() >= 24, 
            String.format("核心线程应该适度扩容，期望>=24，实际=%d", recommendation.getNewCorePoolSize()));
        assertTrue(recommendation.getNewMaximumPoolSize() >= 48, 
            String.format("最大线程应该适度扩容，期望>=48，实际=%d", recommendation.getNewMaximumPoolSize()));
        assertTrue(recommendation.getNewQueueCapacity() >= 700, 
            String.format("队列应该适度扩容，期望>=700，实际=%d", recommendation.getNewQueueCapacity()));
        
        System.out.println("\n平衡型测试结果：");
        System.out.println(String.format("核心线程：16 -> %d", recommendation.getNewCorePoolSize()));
        System.out.println(String.format("最大线程：32 -> %d", recommendation.getNewMaximumPoolSize()));
        System.out.println(String.format("队列容量：500 -> %d", recommendation.getNewQueueCapacity()));
        System.out.println("调整原因：" + recommendation.getReason());
    }
    
    /**
     * 测试用户示例场景：初始队列20，核心线程2，最大线程4
     * 期望扩容后：队列200左右，核心线程8左右，最大线程16左右
     */
    @Test
    void testUserExampleScenario() {
        // 模拟用户示例配置
        ThreadPoolMetrics metrics = createMockMetrics(
            2,    // 核心线程数
            4,    // 最大线程数
            20,   // 队列容量
            18,   // 队列使用数量（90%使用率）
            4,    // 当前线程数
            4,    // 活跃线程数
            50,   // 提交速率
            20,   // 完成速率
            8     // 拒绝任务数
        );
        
        AdjustmentStrategy.AdjustmentRecommendation recommendation = strategy.recommend(metrics);
        
        assertNotNull(recommendation, "用户示例场景应该触发扩容");
        
        // 验证符合用户期望的扩容效果
        assertTrue(recommendation.getNewQueueCapacity() >= 120 && recommendation.getNewQueueCapacity() <= 300, 
            String.format("队列扩容应该在120-300范围内，实际=%d", recommendation.getNewQueueCapacity()));
        assertTrue(recommendation.getNewCorePoolSize() >= 6 && recommendation.getNewCorePoolSize() <= 12, 
            String.format("核心线程扩容应该在6-12范围内，实际=%d", recommendation.getNewCorePoolSize()));
        assertTrue(recommendation.getNewMaximumPoolSize() >= 12 && recommendation.getNewMaximumPoolSize() <= 20, 
            String.format("最大线程扩容应该在12-20范围内，实际=%d", recommendation.getNewMaximumPoolSize()));
        
        System.out.println("\n用户示例场景测试结果：");
        System.out.println(String.format("核心线程：2 -> %d", recommendation.getNewCorePoolSize()));
        System.out.println(String.format("最大线程：4 -> %d", recommendation.getNewMaximumPoolSize()));
        System.out.println(String.format("队列容量：20 -> %d", recommendation.getNewQueueCapacity()));
        System.out.println("调整原因：" + recommendation.getReason());
    }
    
    /**
     * 创建模拟的ThreadPoolMetrics对象
     */
    private ThreadPoolMetrics createMockMetrics(int corePoolSize, int maxPoolSize, int queueCapacity, 
                                               int queueSize, int currentPoolSize, int activeThreads,
                                               double submitRate, double completeRate, long rejectedTasks) {
        double queueUsageRate = (double) queueSize / queueCapacity;
        double threadPoolActivity = currentPoolSize > 0 ? (double) activeThreads / currentPoolSize : 0;
        double averageWaitTime = 50.0;
        long maxWaitTime = 100L;
        long totalSubmittedTasks = 1200L;
        long totalCompletedTasks = 1000L;
        long completedTaskCount = totalCompletedTasks;
        long recentRejectedTasks = rejectedTasks;
        
        return new ThreadPoolMetrics(
            corePoolSize, maxPoolSize, currentPoolSize, activeThreads,
            queueSize, queueCapacity, queueUsageRate, threadPoolActivity,
            submitRate, completeRate, averageWaitTime, maxWaitTime,
            totalSubmittedTasks, totalCompletedTasks, rejectedTasks,
            completedTaskCount, recentRejectedTasks
        );
    }
}